package com.test.scope;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SingletonScope implements Scope{

    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    private final Map<String, Runnable> destructionCallbacks = new ConcurrentHashMap<>(16);

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Object bean = this.singletonObjects.get(name);
        if (bean == null){
            try{
                bean = objectFactory.getObject();
                this.singletonObjects.put(name, bean);
            }catch (Exception e){
                throw e;
            }
        }
        return bean;
    }

    @Override
    public Object remove(String name) {
        Object bean = this.singletonObjects.remove(name);
        this.destructionCallbacks.remove(name);
        return bean;
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        this.destructionCallbacks.put(name, callback);
    }

    @Override
    public String getConversationId() {
        return "singleton";
    }

    public void destroySingletons(){
        String[] singletonNames = this.singletonObjects.keySet().toArray(new String[0]);
        for (String name : singletonNames){
            Runnable callback = this.destructionCallbacks.remove(name);
            if (callback != null){
                try{
                    callback.run();
                }catch (Exception e){
                    System.err.println("Error while destroying singleton with name '" + name + "'");
                }
            }
        }
        this.singletonObjects.clear();
    }
}
